home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / mailbox.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  47KB  |  1,902 lines

  1. /* NOTE: because of size, the previous 'mailbox.c' has been
  2.  * split in 3 parts:
  3.  * mboxcmd.c, containing the 'mbox' subcommands,
  4.  * mailbox.c, containing some user mailbox commands, and
  5.  * mailbox2.c, containing the remaining user commands.
  6.  * 921125 - WG7J
  7.  */
  8. /* There are only two functions in this mailbox code that depend on the
  9.  * underlying protocol, namely mbx_getname() and dochat(). All the other
  10.  * functions can hopefully be used without modification on other stream
  11.  * oriented protocols than AX.25 or NET/ROM.
  12.  *
  13.  * SM0RGV 890506, most work done previously by W9NK
  14.  *
  15.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  16.  *      interface code; everything here uses C eol convention (\n)
  17.  *
  18.  *      Numerous new commands and other changes by SM0RGV, 900120
  19.  *
  20.  * Gateway function now support outgoing connects with the user's call
  21.  * with inverted ssid. Users can connect to system alias as well...
  22.  * See also several mods in socket.c,ax25.c and others
  23.  * 11/15/91, WG7J/PA3DIS
  24.  *
  25.  * Userlogging, RM,VM and KM commands, and R:-line interpretation
  26.  * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
  27.  *
  28.  * Inactivity timeout-disconnect added 920325 and later - WG7J
  29.  *
  30.  * mbxrecvline() now can gobble up suboptions - 94/02/14 VE4WTS
  31.  */
  32. #include <stdio.h>
  33. #include <time.h>
  34. #include <ctype.h>
  35. #ifdef MSDOS
  36. #include <alloc.h>
  37. #endif
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #ifdef  UNIX
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #endif
  44. #include "global.h"
  45. #include "config.h"
  46. #include "timer.h"
  47. #include "proc.h"
  48. #include "socket.h"
  49. #include "usock.h"
  50. #include "session.h"
  51. #include "smtp.h"
  52. #include "dirutil.h"
  53. #include "telnet.h"
  54. #include "ftp.h"
  55. #include "ftpserv.h"
  56. #include "commands.h"
  57. #include "netuser.h"
  58. #include "files.h"
  59. #include "bm.h"
  60. #include "pktdrvr.h"
  61. #include "ax25.h"
  62. #include "mailbox.h"
  63. #include "ax25mail.h"
  64. #include "nr4mail.h"
  65. #include "cmdparse.h"
  66. #include "mailfor.h"
  67.  
  68. #ifdef MAILBOX
  69.  
  70. /* Log all gateway connects to the logfile - WG7J */
  71. #define GWTRACE 1
  72.  
  73. /* By setting the fp to NULL, we can check in exitbbs()
  74.  * wether a tempfile has been closed or not - WG7J
  75.  */
  76. #define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
  77.  
  78. /*
  79. #define MBDEBUG
  80. */
  81.  
  82. extern time_t StartTime;
  83. extern char Myalias[];
  84.  
  85. struct mbx *Mbox;
  86. int BbsUsers;
  87. int Totallogins;
  88. extern char *Mtmsg;
  89. extern int MAttended;
  90. extern unsigned Maxlet;
  91. extern char Mbpasswd[];
  92.  
  93. extern char Noperm[];
  94. extern char Nosock[];
  95. extern char MboxId[];
  96.  
  97. char Loginbanner[] = "\nKA9Q NOS (%s)\n\n";
  98. char Mbwelcome[] = "\nWelcome %s,\n";
  99. char Mbbanner[] = "to the %s TCP/IP Mailbox (%s)\n";
  100. char CurUsers[] = "Currently %d user(s)\n";
  101. char Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
  102. char MsgAborted[] = "Msg aborted\n";
  103.  
  104. #ifdef MAILCMDS
  105. char CcLine[] = "Cc: ";
  106. char Mbwarning[] = "Third Party mail is not permitted.\n";
  107. int MbSent;
  108. int MbRead;
  109. int MbRecvd;
  110. #ifdef MBFWD
  111. int MbForwarded;
  112. #endif
  113. #endif
  114.  
  115. char Mbmenu[] = "Current msg# %d.\n?,"
  116. #ifdef MAILCMDS
  117.         "A,"
  118. #endif
  119.         "B,C,D,E,F,H,I,IH,IP,J,K,"
  120. #ifdef MAILCMDS
  121.         "L,"
  122. #endif
  123.         "M,"
  124. #ifdef NETROM
  125.         "N,NR,"
  126. #endif
  127.         "O,P,"
  128. #ifdef CALLCLI
  129.         "Q,"
  130. #endif
  131. #ifdef MAILCMDS
  132.         "R,S,"
  133. #endif
  134.         "T,U,"
  135. #ifdef MAILCMDS
  136.         "V,"
  137. #endif
  138.         "W,X,Z >\n";
  139.  
  140. extern char Mbnrid[];
  141.  
  142. #ifdef MAILCMDS
  143. #ifdef NETROM
  144. #ifdef CALLCLI
  145. char Longmenu[] = "?)help  A)rea     B)ye    C)onnect D)wnload E)scape F)inger\n"
  146.           "H)elp   I)nfo     IH)eard IP)route J)heard  K)ill   L)ist   M)boxusers\n"
  147.           "N)odes  O)perator P)orts  Q)uery   R)ead    S)end   T)elnet\n"
  148.           "U)pload V)erbose  W)hat   X)pert   Z)ap\n";
  149. #else
  150. char Longmenu[] = "?)help  A)rea     B)ye    C)onnect D)wnload E)scape F)inger\n"
  151.           "H)elp   I)nfo     IH)eard IP)route J)heard  K)ill    L)ist   M)boxusers\n"
  152.           "N)odes  O)perator P)orts  R)ead    S)end    T)elnet\n"
  153.           "U)pload V)erbose  W)hat   X)pert   Z)ap\n";
  154. #endif /*CALLCLI*/
  155. #else /*NETROM*/
  156. #ifdef CALLCLI
  157. char Longmenu[] = "?)help A)rea   B)ye     C)onnect D)wnload E)scape F)inger    H)elp\n"
  158.           "I)nfo  IH)eard IP)route J)heard  K)ill    L)ist   M)boxusers O)perator\n"
  159.           "P)orts Q)uery  R)ead    S)end    T)elnet  U)pload V)erbose\n"
  160.           "W)hat  X)pert  Z)ap\n";
  161.  
  162. #else
  163. char Longmenu[] = "?)help A)rea   B)ye     C)onnect D)wnload E)scape F)inger    H)elp\n"
  164.           "I)nfo  IH)eard IP)route J)heard  K)ill    L)ist   M)boxusers O)perator P)orts\n"
  165.           "R)ead  S)end   T)elnet  U)pload  V)erbose W)hat   X)pert     Z)ap\n";
  166. #endif /*CALLCLI*/
  167. #endif /*NETROM*/
  168. #else /* MAILCMDS */
  169. #ifdef NETROM
  170. #ifdef CALLCLI
  171. char Longmenu[] = "?)help   B)ye    C)onnect   D)wnload E)scape   F)inger H)elp  I)nfo IH)eard\n"
  172.           "IP)route J)heard M)boxusers N)odes   O)perator P)orts  Q)uery T)elnet\n"
  173.           "U)pload  W)hat   X)pert     Z)ap\n";
  174. #else
  175. char Longmenu[] = "?)help   B)ye    C)onnect   D)wnload E)scape   F)inger H)elp   I)nfo   IH)eard\n"
  176.           "IP)route J)heard M)boxusers N)odes   O)perator P)orts  T)elnet U)pload W)hat\n"
  177.           "X)pert   Z)ap\n";
  178. #endif /*CALLCLI*/
  179. #else /*NETROM*/
  180. #ifdef CALLCLI
  181. char Longmenu[] = "?)help   B)ye    C)onnect   D)wnload  E)scape F)inger H)elp   I)nfo  IH)eard\n"
  182.           "IP)route J)heard M)boxusers O)perator P)orts  Q)uery  T)elnet U)pload W)hat\n"
  183.           "X)pert  Z)ap\n";
  184.  
  185. #else
  186. char Longmenu[] = "?)help   B)ye    C)onnect   D)wnload  E)scape F)inger H)elp   I)nfo IH)eard\n"
  187.           "IP)route J)heard M)boxusers O)perator P)orts  T)elnet U)pload W)hat X)pert Z)ap\n";
  188. #endif /*CALLCLI*/
  189. #endif /*NETROM*/
  190. #endif /* MAILCMDS */
  191.  
  192. extern int dombusers __ARGS((int argc,char *argv[],void *p));
  193. extern int dombpast __ARGS((int argc,char *argv[],void *p));
  194. extern int doarea __ARGS((int argc,char *argv[],void *p));
  195. extern int dombstatus __ARGS((int argc,char *argv[],void *p));
  196. extern int dombmailstats __ARGS((int argc,char *argv[],void *p));
  197. void mboxredundant __ARGS((struct mbx *m));
  198. #ifdef CALLCLI
  199. static int dombcallbook __ARGS((int argc,char *argv[],void *p));
  200. #endif
  201. extern int doipheard __ARGS((int argc,char *argv[],void *p));
  202. static int mbx_getname __ARGS((struct mbx *m));
  203. static int dochat __ARGS((int argc,char *argv[],void *p));
  204.  
  205.  
  206. extern int Mbnewmail;
  207. extern int Usenrid;
  208. extern int MBSecure;
  209. extern int Mbsendquery;
  210. #ifdef MBXTDISC
  211. extern int32 Mbtdiscinit;
  212. #endif
  213.  
  214. int
  215. dombports(argc,argv,p)
  216. int argc;
  217. char *argv[];
  218. void *p;
  219. {
  220.     struct iface *ifp;
  221.     struct mbx *m = (struct mbx *)p;
  222.  
  223.     tputs("Available ports:\n");
  224.     for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
  225.     if(ifp->type == CL_AX25 && \
  226.        (!(ifp->flags & HIDE_PORT) || (m->privs & SYSOP_CMD)) ) {
  227.         tprintf("%-7s",ifp->name);
  228.         if(ifp->descr != NULLCHAR)
  229.         tprintf(":  %s",ifp->descr);
  230.         else
  231.         tputc('\n');
  232.     }
  233.     tputc('\n');
  234.     return 0;
  235. }
  236.  
  237. /* This is called by the finger-daemon */
  238. void
  239. listusers(s)
  240. int s;
  241. {
  242.     int outsave;
  243.     struct mbx m;
  244.  
  245.     m.privs = 0;
  246.     m.stype = ' ';
  247.  
  248. #ifdef notdef
  249.     usprintf(s,"\nCurrent remote users:\n");
  250. #endif
  251.     outsave = Curproc->output;
  252.     Curproc->output = s;
  253.     dombusers(0,NULLCHARP,&m);
  254.     Curproc->output = outsave;
  255. }
  256.  
  257. struct mbx *
  258. newmbx()
  259. {
  260.     struct mbx *m,*new;
  261.  
  262.     if((new = (struct mbx *) callocw(1,sizeof(struct mbx))) == NULLMBX)
  263.     return NULLMBX;
  264.     BbsUsers++;
  265.     /* add it into the list */
  266.     if((m=Mbox) == NULLMBX)
  267.     Mbox = new;
  268.     else {
  269.     while(m->next)
  270.         m=m->next;
  271.     m->next = new;
  272.     }
  273.     return new;
  274. }
  275.  
  276. static int
  277. mbx_getname(m)
  278. struct mbx *m;
  279. {
  280.     char *cp;
  281.     FILE *tfp;
  282.     union sp sp;
  283.     char tmp[MAXSOCKSIZE];
  284.     int len = MAXSOCKSIZE;
  285.     int anony = 0;
  286.     int oldmode;
  287.     int founddigit=0;
  288.     int count=0;
  289. #ifdef AX25
  290.     int32 flags;
  291.     int ax_25 = 0;
  292.     struct usock *up;
  293. #endif
  294.  
  295.     sp.p = tmp;
  296.     sp.sa->sa_family = AF_LOCAL;    /* default to AF_LOCAL */
  297.     getpeername(m->user,tmp,&len);
  298.     m->family = sp.sa->sa_family;
  299.     m->path = mallocw(MBXLINE);
  300.     /* This is one of the two parts of the mbox code that depends on the
  301.      * underlying protocol. We have to figure out the name of the
  302.      * calling station. This is only practical when AX.25 or NET/ROM is
  303.      * used. Telnet users have to identify themselves by a login procedure.
  304.      */
  305. #ifdef __GNUC__
  306.     flags = 0;        /* silence "uninitialized" warning */
  307. #endif
  308.     switch(sp.sa->sa_family){
  309. #ifdef  AX25
  310.     case AF_AX25:
  311.     /* If this is not to the convers call, and this port is
  312.      * set for NO_AX25, then disconnect ! - WG7J
  313.      */
  314.     if((m->type != CONF_LINK) && ((up = itop(m->user)) != NULLUSOCK) ) {
  315.         if((flags=up->cb.ax25->iface->flags) & NO_AX25)
  316.         return -1;
  317.     }
  318.     ax_25 = 1;
  319.     /* note fallthrough */
  320.     case AF_NETROM:
  321.         /* NETROM and AX25 socket address structures are "compatible" */
  322.     /* Save user call, in case user wants to use gateway function */
  323.     memcpy(m->call,sp.ax->ax25_addr,AXALEN);
  324.     m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
  325.     pax25(m->name,sp.ax->ax25_addr);
  326.     cp = strchr(m->name,'-');
  327.         if(cp != NULLCHAR)                      /* get rid of SSID */
  328.             *cp = '\0';
  329.         /* SMTP wants the name to be in lower case */
  330.         cp = m->name;
  331.         while(*cp){
  332.             if(isupper(*cp))
  333.                 *cp = tolower(*cp);
  334.             ++cp;
  335.         }
  336.         anony = 1;
  337.         /* Try to find the privileges of this user from the userfile */
  338.     if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony)) == -1){
  339.             m->privs = 0;
  340.             free(m->path);
  341.             m->path = NULLCHAR;
  342.         }
  343.     if(m->privs & EXCLUDED_CMD)
  344.             return -1;
  345.     if(ax_25)
  346.         if(((flags & USERS_ONLY) && (m->privs & IS_BBS)) ||
  347.            ((flags & BBS_ONLY) && !(m->privs & IS_BBS)) ||
  348.            ((flags & SYSOP_ONLY) && !(m->privs & SYSOP_CMD)))
  349.         return -1;
  350.         return 0;
  351. #endif
  352.     case AF_LOCAL:
  353.     case AF_INET:
  354.         m->state = MBX_LOGIN;
  355.     tprintf(Loginbanner,Hostname);
  356.     if(Mtmsg != NULLCHAR)
  357.         tputs(Mtmsg);
  358.         for(;;){
  359.         /* Maximum of 3 tries - WG7J */
  360.         if(count++ == 3)
  361.         return -1;
  362.         oldmode = sockmode(m->user,SOCK_ASCII);
  363.         tputs("login: ");
  364.             usflush(m->user);
  365.         if(mbxrecvline(m) == -1)
  366.                 return -1;
  367.         if(*m->line == 4) /* Control-d */
  368.         return -1;
  369.         if(*m->line == '\0')
  370.                 continue;
  371.  
  372.         /* add a little test to avoid 'Mailfile busy' syndrome - WG7J */
  373.         if((cp=strchr(m->line,'.')) != NULLCHAR)
  374.         *cp = '_';
  375.         if((cp=strchr(m->line,'/')) != NULLCHAR)
  376.         *cp = '_';
  377.         if((cp=strchr(m->line,'\\')) != NULLCHAR)
  378.         *cp = '_';
  379.         if((tfp=fopen(m->line,"w")) == NULL)  /* Invalid name */
  380.         continue;
  381.         fclose(tfp);
  382.         unlink(m->line);
  383.         if(strlen(m->line) < sizeof(m->name))
  384.         strcpy(m->name,m->line);
  385.         else    /* Too long! */
  386.         continue;
  387.             tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
  388.             usflush(m->user);
  389.         sockmode(m->user,SOCK_BINARY);
  390.         if(mbxrecvline(m) == -1)
  391.                 return -1;
  392.             tprintf("%c%c%c",IAC,WONT,TN_ECHO);
  393.             sockmode(m->user,oldmode);
  394.             tputc('\n');
  395.             usflush(m->user);
  396.             /* This is needed if the password was send before the
  397.              * telnet no-echo options were receied. We neeed to
  398.              * flush the eold sequence from the input buffers, sigh
  399.              */
  400.             if(socklen(m->user,0))/* discard any remaining input */
  401.                 recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  402.         if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony))
  403.              != -1){
  404.                 if(anony)
  405.             log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
  406.                 else
  407.                     log(m->user,"MBOX login: %s",m->name);
  408.                 if(m->privs & EXCLUDED_CMD)
  409.                     return -1;
  410. #ifdef AX25
  411.         /*try to set the name as the user-call.
  412.          *this is a very crude test! Be careful...
  413.          *Login must have at leat 1 digit (0-9) in it,
  414.          *and it must be possible to convert it to a call.
  415.          *if this doesn't work, disallow the gateway command,
  416.          *no matter if this was allowed by priviledges or not.
  417.          *Be careful, some one with login name '4us' and
  418.          *permission set to allow gateway/netrom, will
  419.          *go out as '4us-15' or '4us-0' !!!!!
  420.          *11/15/91 WG7J/PA3DIS
  421.          */
  422.         for(cp=m->name;*cp != '\0';cp++)
  423.             if(isdigit((int)*cp))
  424.             break;
  425.         if(*cp != '\0')
  426.             founddigit = 1;
  427.         if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  428.             m->privs &= ~AX25_CMD;
  429.             m->privs &= ~NETROM_CMD;
  430.         }
  431. #else
  432.         m->privs &= ~AX25_CMD;
  433.         m->privs &= ~NETROM_CMD;
  434.  
  435. #endif /* AX25 */
  436.         /* Set the morerows to MAXLIN for telnet logins - WG7J */
  437.         m->morerows = MAXLIN - 1;
  438.         return 0;
  439.             }
  440.         tputs("Login incorrect\n");
  441.         log(m->user,"MBOX Login failed: %s, pw %s",m->name,m->line);
  442.         mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
  443.             *m->name = '\0';        /* wipe any garbage */
  444.         }
  445.     }
  446.     return 0;
  447. }
  448.  
  449. /* put up the prompt */
  450. void
  451. putprompt(m)
  452. struct mbx *m;
  453. {
  454.     char area[64];
  455.     char *cp1,*cp2;
  456.  
  457. #ifdef MAILCMDS
  458.     if(m->sid & MBX_SID)
  459.     tputs(">\n");
  460.     else {
  461. #endif
  462.     if(m->sid & MBX_NRID)
  463.         tputs(Mbnrid);
  464. #ifdef MAILCMDS
  465.     if(m->sid & MBX_AREA) {
  466.         cp1 = m->area;
  467.         cp2 = area;
  468.         /* Convert / and \ into . */
  469.         while(*cp1 != '\0') {
  470.         if(*cp1=='/')
  471.             *cp2 = '.';
  472.         else
  473.             *cp2 = *cp1;
  474.         cp1++;
  475.         cp2++;
  476.         }
  477.         *cp2 = '\0';
  478.         tprintf("Area: %s ",area);
  479.     }
  480. #endif
  481.     tprintf((m->sid & MBX_EXPERT) ? ">\n" : Mbmenu, m->current);
  482. #ifdef MAILCMDS
  483.     }
  484. #endif
  485. }
  486.  
  487. #ifdef MBXTDISC
  488. /* Mailbox user has been idle for too long,
  489.  * disconnect the socket - WG7J
  490.  */
  491. void
  492. #ifdef PROTOTYPES
  493. mboxredundant(struct mbx *m)
  494. #else
  495. mboxredundant(m)
  496. struct mbx *m;
  497. #endif
  498. {
  499.     struct usock *up;
  500.  
  501.     /* nasty hack! we may have screwed up reference count */
  502.     /* by invoking newproc("smtp_send",....); Fudge it!   */
  503.     if((up = itop(m->user)) != NULLUSOCK)
  504.     up->refcnt = 1;
  505.  
  506.     /* Close the socket*/
  507.     close_s(m->user);
  508.     return; /* Keep lint happy */
  509. }
  510. #endif
  511.  
  512.  
  513. /* Incoming mailbox session */
  514. void
  515. mbx_incom(s,t,p)
  516. int s;
  517. void *t;
  518. void *p;
  519. {
  520. #ifdef TIPMAIL
  521. #ifdef XMODEM
  522.     struct tipcb *tip;
  523. #endif
  524. #endif
  525.     struct mbx *m,*mp,*pp;
  526.     struct usock *up;
  527.     char *buf[3];
  528.     char tmp[AXBUF];
  529.     int rval;
  530.     FILE *fp;
  531.  
  532. /*
  533.     if((up = itop(s)) != NULLUSOCK)
  534.     if(up->iface->flags & NO_AX25)
  535.  */
  536.  
  537.     sockmode(s,SOCK_ASCII);
  538.     sockowner(s,Curproc);   /* We own it now */
  539.     /* Secede from the parent's sockets, and use the network socket that
  540.      * was passed to us for both input and output. The reference
  541.      * count on this socket will still be 1; this allows the domboxbye()
  542.      * command to work by closing that socket with a single call.
  543.      * If we return, the socket will be closed automatically.
  544.      */
  545.     close_s(Curproc->output);
  546.     close_s(Curproc->input);
  547.     Curproc->output = Curproc->input = s;
  548.  
  549.     /* We'll do our own flushing right before we read input */
  550.     setflush(s,-1);
  551.  
  552.     if((m = newmbx()) == NULLMBX){
  553.     tputs("Too many mailbox sessions\n");
  554.         return;
  555.     }
  556.  
  557.     m->user = s;
  558.     m->escape = 20;     /* default escape character is Ctrl-T */
  559.     m->linemode = 0;
  560.     m->type = (int) t;
  561.  
  562. #ifdef TIPMAIL
  563. #ifdef XMODEM
  564.     if(m->type == TIP_LINK) {
  565.         tip = (struct tipcb *) p;
  566.         tip->raw=0;
  567.         m->tip=tip;    
  568.     } 
  569. #endif        
  570. #endif
  571.  
  572.     /* discard any remaining input */
  573. /*
  574.     while(socklen(s,0))
  575.     recv_mbuf(s,NULL,0,NULLCHAR,0);
  576.     */
  577.     
  578.     /* get the name of the remote station */
  579.     if(mbx_getname(m) == -1) {
  580.         exitbbs(m);
  581.         return;
  582.     }
  583.     Totallogins++;
  584.  
  585. #ifdef CONVERS
  586.     if((int)t & CONF_LINK) {
  587.     if(m->privs & NO_CONVERS) {
  588.         tputs(Noperm);
  589.         mail_error("%s: conv-call access denied\n",m->name);
  590.     } else {
  591.         m->state = MBX_CONVERS;
  592.         chname(Curproc,"conference");
  593.         log(s,"open CONF");
  594.         mbox_converse(m);
  595.     }
  596.     /* now free it from list */
  597.     for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
  598.     if(pp==NULLMBX)     /* first one on list */
  599.         Mbox = m->next;
  600.     else
  601.         pp->next = m->next;
  602.     free((char *)m);
  603.     BbsUsers--;
  604.     close_s(Curproc->output);
  605.     return;
  606.     }
  607. #endif
  608.  
  609. #ifdef TTYCALL
  610.     if((int)t & TTY_LINK) {
  611.     int ostate = m->state;
  612.  
  613.     m->state = MBX_CHAT;
  614.     chname(Curproc,"ttylink");
  615.     log(s,"open TTYLINK");
  616.     if (dochat(0, 0, m) == 2)
  617.     {
  618.         /* now free it from list */
  619.         for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
  620.         if(pp==NULLMBX)     /* first one on list */
  621.         Mbox = m->next;
  622.         else
  623.         pp->next = m->next;
  624.         free((char *)m);
  625.         BbsUsers--;
  626.         close_s(Curproc->output);
  627.         return;
  628.     }
  629.     tputs("Chaining to BBS...\n");
  630.     m->state = ostate;
  631.     }
  632. #endif
  633.  
  634.     log(s,"open MBOX");
  635. #ifdef MBXTDISC
  636.     /*Start inactivity timer - WG7J */
  637.     set_timer(&m->tdisc,Mbtdiscinit * 1000L);
  638.     m->tdisc.func = (void(*)__FARGS((void*)))mboxredundant;
  639.     m->tdisc.arg = m;
  640.     start_timer(&m->tdisc);
  641. #endif
  642.     if(m->privs & IS_BBS)
  643.     m->sid = MBX_SID; /*force bbs status*/
  644.     else
  645.     if(m->privs & IS_EXPERT)
  646.         m->sid |= MBX_EXPERT;
  647.  
  648.     loguser(m);
  649.     m->state = MBX_CMD;     /* start in command state */
  650. #ifdef MAILCMDS
  651.     tputs(MboxId);
  652. #endif
  653.  
  654.     /* Say 'hello' only if user is not a bbs - WG7J */
  655. #ifdef MAILCMDS
  656.     if(!(m->sid & MBX_SID)) {
  657. #endif
  658.     tprintf(Mbwelcome,m->name);
  659. #ifdef AX25
  660.     if(m->family == AF_INET)
  661. #endif
  662.         tprintf(Mbbanner,Hostname,Version);
  663. #ifdef AX25
  664.     else
  665.         tprintf(Mbbanner,pax25(tmp,Mycall),Version);
  666. #endif
  667.     /* How many users are there currently ? */
  668.     tprintf(CurUsers,BbsUsers);
  669.  
  670. #ifdef MAILCMDS
  671.     /* Do we accept third party mail ? */
  672.     if(!ThirdParty)
  673.             tputs(Mbwarning);
  674. #endif
  675.     tputc('\n');
  676.  
  677.     /* Is there a message of the day ? */
  678.     if((fp = fopen(Motdfile,READ_TEXT)) != NULLFILE) {
  679.         sendfile(fp,m->user,ASCII_TYPE,0);
  680.         fclose(fp);
  681.     }
  682.  
  683. #ifdef MAILCMDS
  684. #ifdef USERLOG
  685.     /* Tell about new arrived mail in message areas - WG7J */
  686.     if(Mbnewmail)
  687.         listnewmail(m);
  688. #endif
  689. #endif
  690.  
  691.      /* make sure user gets it */
  692. /*        usflush(m->user); done in mbxrecvline() */
  693.  
  694. #ifdef MAILCMDS
  695.     /* Enable our local message area,
  696.      * only if we're not a bbs - WG7J
  697.      */
  698.     buf[1] = m->name;
  699.     doarea(2,buf,m);
  700.     }
  701. #endif
  702.  
  703.     /* Send prompt */
  704.     putprompt(m);
  705.  
  706.     while(mbxrecvline(m) != -1){
  707.     if((rval = mbx_parse(m)) == -2)
  708.             break;
  709.         if(rval == 1)
  710.         tputs("Bad syntax.\n");
  711. #ifdef notdef
  712.     tprintf("last = %ld, new last = %ld\n",m->lastread,m->newlastread);
  713. #endif
  714. #ifdef MAILCMDS
  715.     /* Only tell about new mail when in our own area - WG7J */
  716.     if(!(m->sid & MBX_SID) && !strcmp(m->name,m->area) &&
  717.         (isnewprivmail(m) > 0L) )
  718.         tputs("You have new mail. Please Kill when read!\n");
  719.     /* Do not check mailfile if we're bbs, saves a tmpfile- WG7J*/
  720.     if(!(m->sid & MBX_SID))
  721.         scanmail(m);
  722. #endif
  723.     putprompt(m);
  724.     m->state = MBX_CMD;
  725.     }
  726.     exitbbs(m);
  727.  
  728.     /* by invoking newproc("smtp_send",....); Fudge it!   */
  729.     if((up = itop(Curproc->output)) != NULLUSOCK)
  730.     up->refcnt = 1;
  731.     close_s(Curproc->output);
  732.  
  733. }
  734.  
  735. void
  736. exitbbs(m)
  737. struct mbx *m;
  738. {
  739.     struct mbx *mp,*pp;
  740.  
  741. #ifdef MBXTDISC
  742.     stop_timer(&m->tdisc);
  743. #endif
  744.     closenotes(m);
  745.     free(m->to);
  746.     free(m->tofrom);
  747.     free(m->origto);
  748.     free(m->origbbs);
  749.     free(m->subject);
  750.     free(m->date);
  751.     free(m->tomsgid);
  752.     free(m->path);
  753.     /* Close the tempfiles if they are not nullpointers - WG7J */
  754.     if(m->tfile != (FILE *) 0)
  755.     fclose(m->tfile);
  756.     if(m->tfp != (FILE *) 0)
  757.     fclose(m->tfp);
  758.     if(m->stdinbuf != NULLCHAR)
  759.         free(m->stdinbuf);
  760.     if(m->stdoutbuf != NULLCHAR)
  761.         free(m->stdoutbuf);
  762.     free((char *)m->mbox);
  763.     /* now free it from list */
  764.     for(mp=Mbox,pp=NULLMBX;mp && mp!=m;pp=mp,mp=mp->next);
  765.     if(!mp)
  766.     /* what happened ??? */
  767.     return;
  768.     if(pp==NULLMBX)     /* first one on list */
  769.     Mbox = Mbox->next;
  770.     else
  771.     pp->next = m->next;
  772.     free((char *)m);
  773.     BbsUsers--;
  774. }
  775.  
  776. /**********************************************************************/
  777.  
  778. extern int dombconnect __ARGS((int argc,char *argv[],void *p));
  779. #ifdef CALLBOOK
  780. static int dombcall __ARGS((int argc,char *argv[],void *p));
  781. #endif
  782. extern int dodownload __ARGS((int argc,char *argv[],void *p));
  783. extern int dombupload __ARGS((int argc,char *argv[],void *p));
  784. extern int dowhat __ARGS((int argc,char *argv[],void *p));
  785. extern int dozap __ARGS((int argc,char *argv[],void *p));
  786. static int dosend __ARGS((int argc,char *argv[],void *p));
  787. extern int dosid __ARGS((int argc,char *argv[],void *p));
  788. extern int dosysop __ARGS((int argc,char *argv[],void *p));
  789. extern int dostars __ARGS((int argc,char *argv[],void *p));
  790. static int dombhelp __ARGS((int argc,char *argv[],void *p));
  791. static int dombiproute __ARGS((int argc,char *argv[],void *p));
  792. extern int dombtelnet __ARGS((int argc,char *argv[],void *p));
  793. extern int dombfinger __ARGS((int argc,char *argv[],void *p));
  794. static int dombexpert __ARGS((int argc,char *argv[],void *p));
  795. static int dombjheard __ARGS((int argc,char *argv[],void *p));
  796. int dombmovemail __ARGS((int argc,char *argv[],void *p));
  797. void gw_alarm __ARGS((void *p));
  798. void gw_input __ARGS((int s,void *notused,void *p));
  799. void gw_superv __ARGS((int null,void *proc,void *p));
  800. extern int mbx_to __ARGS((int argc,char *argv[],void *p));
  801. extern int mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra));
  802. int msgidcheck __ARGS((char *string));
  803. extern int thirdparty __ARGS((struct mbx *m));
  804. #ifdef NETROM
  805. extern int dombnrnodes __ARGS((int argc,char *argv[],void *p));
  806. extern int donrneighbour __ARGS((int argc,char *argv[],void *p));
  807. #endif
  808.  
  809. static struct cmds DFAR Mbcmds[] = {
  810.     "",             doreadnext,     0, 0, NULLCHAR,
  811.     "?",            dombhelp,       0, 0, NULLCHAR,
  812. #ifdef MAILCMDS
  813.     "area",     doarea,     0, 0, NULLCHAR,
  814. #endif
  815.     "bye",      domboxbye,  0, 0, NULLCHAR,
  816.     "connect",  dombconnect,0, 0, NULLCHAR,
  817. #ifdef CALLBOOK
  818.     "call",     dombcall,   0, 0, NULLCHAR,
  819. #endif
  820. #ifdef XMODEM
  821.     "download", dodownload, 0, 2, "D[U|X] <filename>",
  822. #else
  823.     "download", dodownload, 0, 2, "D[U] <filename>",
  824. #endif        
  825.     "escape",       dombescape,     0, 0, NULLCHAR,
  826.     "finger",       dombfinger,     0, 0, NULLCHAR,
  827.     "help",         dombhelp,       0, 0, NULLCHAR,
  828.     "info",         dombhelp,       0, 0, NULLCHAR,
  829.     "iheard",   doipheard,0, 0, NULLCHAR,
  830.     "iproute",  dombiproute,0, 0, NULLCHAR,
  831. #ifdef  AX25
  832.     "jheard",   dombjheard, 0, 0, NULLCHAR,
  833. #endif
  834. #ifdef MAILCMDS
  835.     "kill",     dodelmsg,   0, 0, NULLCHAR,
  836.     "list",     dolistnotes,0, 0, NULLCHAR,
  837. #endif
  838.     "mboxusers",dombusers,  0, 0, NULLCHAR,
  839. #ifdef NETROM
  840.     "nodes",    dombnrnodes,0, 0, NULLCHAR,
  841.     "nroutes",  donrneighbour, 0, 0, NULLCHAR,
  842. #endif
  843.     "operator", dochat,     0, 0, NULLCHAR,
  844.     "ports",    dombports,  0, 0, NULLCHAR,
  845. #ifdef CALLCLI
  846.     "query", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
  847. #endif
  848. #ifdef MAILCMDS
  849.     "read",     doreadmsg,  0, 0, NULLCHAR,
  850.     "send",         dosend,         0, 0, NULLCHAR,
  851. #endif
  852.     "telnet",   dombtelnet, 0, 2, "T hostname",
  853. #ifdef XMODEM
  854.     "upload",   dombupload, 0, 2, "U[X] <filename>",
  855. #else
  856.     "upload",   dombupload, 0, 2, NULLCHAR,
  857. #endif    
  858. #ifdef MAILCMDS
  859.     "verbose",  doreadmsg,  0, 0, NULLCHAR,
  860. #endif
  861.     "what",     dowhat,     0, 0, NULLCHAR,
  862.     "xpert",    dombexpert, 0, 0, NULLCHAR,
  863.     "zap",      dozap,      0, 2, "Z filename",
  864. #ifdef MAILCMDS
  865.     "[",        dosid,      0, 0, NULLCHAR,
  866. #ifdef  AX25
  867. #ifdef MBFWD
  868.     "f>",       dorevfwd,   0, 0, NULLCHAR,
  869. #endif
  870. #endif
  871. #endif
  872.     "@",        dosysop,    0, 0, NULLCHAR,
  873.     "***",          dostars,        0, 0, NULLCHAR,
  874.     NULLCHAR,       NULLFP((int,char**,void*)),         0, 0, "Huh?",
  875. };
  876.  
  877. /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
  878.  * They have to be treated specially since cmdparse() wants a space between
  879.  * the actual command and its arguments.
  880.  * "SP FOO" is converted to "s  foo" and the second command letter is saved
  881.  * in m->stype. Longer commands like "SEND" are unaffected, except for
  882.  * commands starting with "[", i.e. the SID, since we don't know what it will
  883.  * look like.
  884.  */
  885. static char twocmds[] = "aslrd[muvkx";    /* S,L,R,D,M,U,V,K,X are two-letter commands */
  886.  
  887. int
  888. mbx_parse(m)
  889. struct mbx *m;
  890. {
  891.     char *cp;
  892.     int i;
  893.     char *newargv[2];
  894.     /* Translate entire buffer to lower case */
  895.     for (cp = m->line; *cp != '\0'; ++cp)
  896.         if(isupper(*cp))
  897.             *cp = tolower(*cp);
  898.     /* Skip any spaces at the begining */
  899.     for(cp = m->line;isspace(*cp);++cp)
  900.         ;
  901.     m->stype = ' ';
  902.     if(*cp != '\0' && *(cp+1) != '\0')
  903.     for(i=0; i<strlen(twocmds); ++i){
  904.         if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
  905.          || *cp == '[')){
  906.             if(islower(*(++cp)))
  907.                 m->stype = toupper(*cp); /* Save the second character */
  908.             else
  909.                 m->stype = *cp;
  910.             *cp = ' ';
  911.             break;
  912.         }
  913.     }
  914. #ifdef MAILCMDS
  915.     /* See if the input line consists solely of digits */
  916.     cp = m->line;
  917.     for(cp = m->line;isspace(*cp);++cp)
  918.         ;
  919.     newargv[1] = cp;
  920.     for(;*cp != '\0' && isdigit(*cp);++cp)
  921.         ;
  922.     if(*cp == '\0' && strlen(newargv[1]) > 0) {
  923.     newargv[0] = "r";
  924.     return doreadmsg(2,newargv,(void *)m);
  925.     }
  926.     else
  927. #endif
  928.     return cmdparse(Mbcmds,m->line,(void *)m);
  929. }
  930.  
  931. /* This works like recvline(), but telnet options are answered and the
  932.  * terminating newline character is not put into the buffer. If the
  933.  * incoming character equals the value of escape, any queued input is
  934.  * flushed and -2 returned.
  935.  */
  936. int
  937. mbxrecvline(m)
  938. struct mbx *m;
  939. {
  940.     int s = m->user;
  941.     int escape = m->escape;
  942.     char *buf = m->line;
  943.     int c, cnt = 0, opt, cl;
  944.  
  945.     if(buf == NULLCHAR)
  946.         return 0;
  947.     usflush(Curproc->output);
  948. #ifdef MBXTDISC
  949.     start_timer(&m->tdisc);
  950. #endif
  951.     while((c = recvchar(s)) != EOF){
  952.         if(c == IAC){           /* Telnet command escape */
  953.             if((c = recvchar(s)) == EOF)
  954.                 break;
  955.             if(c >= 250 && c < 255 && (opt = recvchar(s)) != EOF){
  956.                 switch(c){
  957.                 case SB:
  958.                     opt=recvchar(s); /* Get the real option */
  959.                     if(opt==EOF) break;
  960.                     cl=opt;
  961.                     c=recvchar(s);
  962.                     /* Gobble up until we see IAC SE */
  963.                     while((c!=EOF) && !(cl==IAC && c==SE)){
  964.                         /* maybe check for timeout here, in case someone
  965.                            happened to send a binary file with the IAC SB
  966.                            sequence in it. */
  967.                         cl=c; /* keep track of second last char read */
  968.                         c=recvchar(s);
  969.                     }
  970.                     /* and tell the client where to go... */
  971.                     /* tprintf("%c%c%c",IAC,WONT,opt); */
  972.                     break;
  973.                 case WILL:
  974.                     if(opt==TN_LINEMODE){
  975.                         m->linemode = 1;
  976.                         /* we WANT linemode */
  977.                         tprintf("%c%c%c",IAC,DO,opt);
  978.                         /* Tell client to do editing */
  979.                         tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
  980.                     }
  981.                     else{
  982.                         tprintf("%c%c%c",IAC,DONT,opt);
  983.                     }
  984.                     break;
  985.                 case WONT:
  986.                     tprintf("%c%c%c",IAC,DONT,opt);
  987.                     break;
  988.                 case DO:
  989.                     tprintf("%c%c%c",IAC,WONT,opt);
  990.                     break;
  991.                 case DONT:
  992.                     tprintf("%c%c%c",IAC,WONT,opt);
  993.                 }
  994. /* to be fixed                  usflush(Curproc->output);*/
  995.                 continue;
  996.             }
  997.             if(c != IAC && (c = recvchar(s)) == EOF)
  998.                 break;
  999.         }
  1000.         /* ordinary character */
  1001.         if(c == '\r' || c == '\n')
  1002.             break;
  1003.         if(uchar(c) == escape){
  1004.             if(socklen(s,0)) /* discard any remaining input */
  1005.                 recv_mbuf(s,NULL,0,NULLCHAR,0);
  1006.             cnt = -2;
  1007.             break;
  1008.         }
  1009.     /* Handle <del> chars - from wa7tas */
  1010.     if(c == 8) {
  1011.         if(cnt > 0) {
  1012.         *--buf = 0;
  1013.         cnt--;
  1014.         }
  1015.     } else {
  1016.         *buf++ = c;
  1017.         ++cnt;
  1018.     }
  1019.     if(cnt == MBXLINE - 1)
  1020.             break;
  1021.     }
  1022.     if(c == EOF && cnt == 0)
  1023.         return -1;
  1024.     *buf = '\0';
  1025. #ifdef MBXTDISC
  1026.     /* Restart the timeout-timer - WG7J*/
  1027.     start_timer(&m->tdisc);
  1028. #endif
  1029.     return cnt;
  1030. }
  1031.  
  1032. extern void updatedefaults(struct mbx *);
  1033.  
  1034. int
  1035. domboxbye(argc,argv,p)
  1036. int argc;
  1037. char *argv[];
  1038. void *p;
  1039. {
  1040.     struct mbx *m;
  1041.  
  1042.     m = (struct mbx *)p;
  1043.  
  1044.     /* for bbs's, just disconnect */
  1045.     if(m->sid & MBX_SID)
  1046.         return -2;
  1047.  
  1048. #ifdef USERLOG
  1049.     setlastread(m);
  1050.     updatedefaults(m);
  1051. #endif
  1052.     /* Now say goodbye */
  1053.     tprintf("\nThank you %s,\nfor calling the %s NOS Tcp/Ip Mailbox.\n\n",m->name,
  1054.         Hostname);
  1055. #ifdef ALLSERV
  1056.     if(m->type == TIP_LINK)
  1057.     tputs("Please hang up now.\n");
  1058. #endif
  1059.     usflush(m->user);
  1060.     return -2;      /* signal that exitbbs() should be called */
  1061. }
  1062.  
  1063. static int
  1064. dombhelp(argc,argv,p)
  1065. int argc;
  1066. char *argv[];
  1067. void *p;
  1068. {
  1069.     char buf[255];
  1070.     int i;
  1071.     FILE *fp;
  1072.     if(*argv[0] == '?') {
  1073.     tputs(Longmenu);
  1074.         return 0;
  1075.     }
  1076.     buf[0] = '\0';
  1077.     if(argc > 1)
  1078.         for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
  1079.             if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
  1080.                 sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
  1081.                 break;
  1082.             }
  1083.     if(buf[0] == '\0')
  1084.     if(*argv[0] == 'i') {
  1085.         /* INFO command */
  1086.         tprintf(Nosversion,Version);
  1087.         sprintf(buf,"%s/info.hlp",Helpdir);
  1088.     } else
  1089.             sprintf(buf,"%s/help.hlp",Helpdir);
  1090.     if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  1091.         sendfile(fp,Curproc->output,ASCII_TYPE,0);
  1092.         fclose(fp);
  1093.     } else {
  1094.     if(*argv[0]!='i')
  1095.         tputs("No help available.\n");
  1096.     }
  1097.     return 0;
  1098. }
  1099.  
  1100. extern void dumproute __ARGS((struct route *rp,char *p));
  1101. extern char RouteHeader[];
  1102.  
  1103. /* Show non-private routes only */
  1104. int
  1105. dombiproute(argc,argv,p)
  1106. int argc;
  1107. char *argv[];
  1108. void *p;
  1109. {
  1110.     register int i,bits;
  1111.     register struct route *rp;
  1112.     char buf[85];
  1113.  
  1114.     tputs(RouteHeader);
  1115.     for(bits=31;bits>=0;bits--){
  1116.         for(i=0;i<HASHMOD;i++){
  1117.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  1118.         if(!(rp->flags & RTPRIVATE)) {
  1119.             dumproute(rp,buf);
  1120.             if(tprintf("%s\n",&buf[4]) == EOF)
  1121.             return 0;
  1122.         }
  1123.             }
  1124.         }
  1125.     }
  1126.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
  1127.     dumproute(&R_default,buf);
  1128.     if(tprintf("%s\n",&buf[4]) == EOF)
  1129.         return 0;
  1130.     }
  1131.     return 0;
  1132. }
  1133.  
  1134. #ifdef MAILCMDS
  1135.  
  1136. extern char Badmsg[];
  1137. extern char Nomail[];
  1138.  
  1139. /* Move messages from current area to another */
  1140. int
  1141. dombmovemail(argc,argv,p)
  1142. int argc;
  1143. char *argv[];
  1144. void *p;
  1145. {
  1146.     int num,i;
  1147.     int move[NARG];
  1148.     char *to;
  1149.     struct mbx *m;
  1150.     char buf[MBXLINE];
  1151. #ifdef notdef
  1152.     char *cp;
  1153. #endif
  1154.     FILE * Mfile;           /* file to move to */
  1155.     struct let *cmsg;
  1156.     long size;
  1157.     int thisone;
  1158.  
  1159.     m = (struct mbx *)p;
  1160.  
  1161.     if(argc == 1) {
  1162.     tputs("Syntax: MM area - moves current message\n"
  1163.           "        MM n1 [n2...] area - move message n1 (n2...)\n");
  1164.     return 0;
  1165.     }
  1166.     if(m->mfile == NULLFILE) {
  1167.     tputs(Nomail);
  1168.     return 0;
  1169.     }
  1170.     if(argc == 2) {
  1171.     /* NO message #, use current message */
  1172.     num = 1;
  1173.     to = argv[1];
  1174.     move[0] = m->current;
  1175.     } else {
  1176.     /* Scan all message # to move */
  1177.     num=0;
  1178.     for(i=1;i<argc-1;i++) {
  1179.         if( (move[num]=atoi(argv[i])) != 0 ) {
  1180.         if(move[num] <= m->nmsgs)
  1181.             num++;
  1182.         } else
  1183.         tprintf(Badmsg,argv[i]);
  1184.     }
  1185.     to = argv[argc-1];
  1186.     }
  1187. #ifdef notdef
  1188.     /* translate '.' and '\\' to '/' */
  1189.     for(cp=to;*cp!='\0';cp++)
  1190.         if((*cp == '.') || (*cp == '\\'))
  1191.         *cp = '/';
  1192. #endif
  1193.  
  1194.     /* Now try to lock the destination file */
  1195.     if(mlock(Mailspool,to) == -1) {
  1196.     tprintf("Can't lock '%s', please try later\n",to);
  1197.     return 0;
  1198.     }
  1199.     /* open the destination file for appending */
  1200.     sprintf(buf,"%s/%s.txt",Mailspool,to);
  1201.     if((Mfile=fopen(buf,"a")) == NULLFILE) {
  1202.     tprintf("Can't open '%s'\n",buf);
  1203.     rmlock(Mailspool,to);
  1204.     return 0;
  1205.     }
  1206.     /* Okay, let's do the work */
  1207.     for(i=0;i<num;i++) {
  1208.     thisone = move[i];
  1209.     cmsg = &m->mbox[thisone];
  1210.     /* find start of this message */
  1211.     fseek(m->mfile,cmsg->start,0);
  1212.     size = cmsg->size;
  1213.     /* now read this message */
  1214.     while(size > 0 && fgets(buf,MBXLINE,m->mfile)!= NULLCHAR) {
  1215.         fputs(buf,Mfile);
  1216.         size -= strlen(buf);
  1217.     }
  1218.     /* delete this message */
  1219.     cmsg->status |= BM_DELETE;
  1220.     m->change = 1;
  1221.     tprintf("Message %d moved...\n",thisone);
  1222.     }
  1223.     fclose(Mfile);
  1224.     rmlock(Mailspool,to);
  1225.     return 0;
  1226. }
  1227. #endif
  1228.  
  1229. static int
  1230. dombexpert(argc,argv,p)
  1231. int argc;
  1232. char *argv[];
  1233. void *p;
  1234. {
  1235.     struct mbx *m;
  1236.  
  1237.     m = (struct mbx *)p;
  1238.  
  1239.     switch(m->stype) {
  1240.     case 'M':
  1241.     if(argc == 1)
  1242.         tprintf("-more- after %d lines\n",m->morerows);
  1243.     else {
  1244.         m->morerows = atoi(argv[1]);
  1245.     }
  1246.     break;
  1247.     case 'A':
  1248.     m->sid ^= MBX_AREA;
  1249.     break;
  1250.     case 'N':
  1251.     m->sid ^= MBX_NRID;
  1252.     break;
  1253.     default:
  1254.     m->sid ^= MBX_EXPERT;
  1255.     break;
  1256.     }
  1257.     return 0;
  1258. }
  1259.  
  1260. extern char SysopBusy[];
  1261.  
  1262. static int
  1263. dochat(argc,argv,p)
  1264. int argc;
  1265. char *argv[];
  1266. void *p;
  1267. {
  1268.     char buf[8], *newargv[3];
  1269.     struct mbx *m;
  1270.  
  1271.     m = (struct mbx *)p;
  1272.  
  1273.     if(MAttended){
  1274.     m->state = MBX_CHAT;
  1275.     newargv[0] = "C";
  1276.         newargv[1] = Hostname;
  1277.         sprintf(buf,"%d",IPPORT_TTYLINK);
  1278.         newargv[2] = buf;
  1279.         return dombtelnet(3,newargv,p);
  1280.     }
  1281.     else {
  1282.     tputs(SysopBusy);
  1283.     }
  1284.     /* It returns only after a disconnect or refusal */
  1285.     return 0;
  1286. }
  1287.  
  1288. #ifdef AX25
  1289. static int
  1290. dombjheard(argc,argv,p)
  1291. int argc;
  1292. char *argv[];
  1293. void *p;
  1294. {
  1295.     struct iface *ifp;
  1296.     struct mbx *m = (struct mbx *)p;
  1297.  
  1298.     if(argc > 1){
  1299.     if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
  1300.        ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
  1301.         tprintf(Badinterface,argv[1]);
  1302.         return 0;
  1303.         }
  1304.         axheard(ifp);
  1305.         return 0;
  1306.     }
  1307.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  1308.     if((ifp->flags & LOG_AXHEARD)  && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
  1309.         if(axheard(ifp) == EOF)
  1310.         break;
  1311.     }
  1312.     return 0;
  1313. }
  1314. #endif
  1315.  
  1316. #ifdef CALLBOOK
  1317. extern char *InetCallserver;
  1318. extern char *InetCallserverport;
  1319.  
  1320. /*This is a simple way of estiblishing a connection
  1321.  *to a callbook-server via tcp - WG7J
  1322.  */
  1323. static int
  1324. dombcall(argc,argv,p)
  1325. int argc;
  1326. char *argv[];
  1327. void *p;
  1328. {
  1329.     char *newargv[3];
  1330.  
  1331.     if(InetCallserver!=NULLCHAR){
  1332.     newargv[0] = "C";
  1333.     newargv[1] = InetCallserver;
  1334.     newargv[2] = InetCallserverport;
  1335.         return dombtelnet(3,newargv,p);
  1336.     }
  1337.     else {
  1338.     tputs("Internet callserver not configured\n");
  1339.     }
  1340.     /* It returns only after a disconnect or refusal */
  1341.     return 0;
  1342. }
  1343.  
  1344. #endif /*CALLBOOK*/
  1345.  
  1346. #ifdef CALLCLI
  1347. static int
  1348. dombcallbook(argc,argv,p)
  1349. int argc;
  1350. char *argv[];
  1351. void *p;
  1352. {
  1353.     struct mbx *m;
  1354.   char buf[8], *newargv[3];
  1355.   extern char *Callserver;
  1356.   int req, ret = 0;
  1357.  
  1358.   m = (struct mbx *) p;
  1359. /*   tprintf("Looking up - %s - in the callbook at %s\n",argv[1],Callserver);*/
  1360.   sprintf(buf,"%d",IPPORT_CALLDB);
  1361.   newargv[0] = "C";
  1362.   newargv[1] = Callserver;
  1363.   newargv[2] = buf;
  1364.  
  1365.   for (req = 1; req < argc; req++)  {
  1366.   if (argv[req] == NULLCHAR) return ret;
  1367.   m->startmsg = mallocw(80);  /* is freed each time by gw_connect()         */
  1368.   sprintf(m->startmsg,"%s\n", argv[req]);
  1369.   log(m->user, "%s checking callbook: %s",m->name,argv[req]);
  1370.   tprintf("Looking for \" %s \" in the callbook at %s\n",argv[req],Callserver);
  1371.   ret = dombtelnet(3,newargv,p);
  1372.   }
  1373.   return ret; /* It looks like all possible returns are zero anyway!    */
  1374. }
  1375. #endif
  1376.  
  1377. #ifdef MAILCMDS
  1378.  
  1379. extern int Mbloophold;
  1380.  
  1381. /*Some additional security - WG7J
  1382.  *NO_3PARTY =  disallow all 3rd party mail
  1383.  *NO_SENDCMD = only allow mail to sysop
  1384.  */
  1385. extern int NoBid;
  1386.  
  1387. static int
  1388. dosend(argc,argv,p)
  1389. int argc;
  1390. char *argv[];
  1391. void *p;
  1392. {
  1393.     int cccnt = 0, fail = 0;
  1394.     char *host, *cp, fullfrom[MBXLINE], sigwork[LINELEN], *rhdr = NULLCHAR;
  1395.     struct list *ap, *cclist = NULLLIST;
  1396.     struct mbx *m;
  1397.     FILE *fp;
  1398. #ifdef notdef
  1399.     time_t now;
  1400. #endif
  1401.     int done = 0;
  1402.     char *cp2;
  1403.     int c;
  1404.  
  1405. #ifdef RLINE
  1406.     struct tm t;
  1407. #define ODLEN   16
  1408. #define OBLEN   32
  1409.     char tmpline[MBXLINE];
  1410.     char fwdbbs[NUMFWDBBS][FWDBBSLEN+1];
  1411.     int myfwds = 0;
  1412.     int i;
  1413.     int zulu;
  1414.     int check_r = 0;
  1415.     int found_r = 0;
  1416.     char origdate[ODLEN];
  1417.     char origbbs[OBLEN];
  1418.     int loops = 0;
  1419.     char Me[15];
  1420.  
  1421.     origdate[0] = '\0';
  1422.     origbbs[0] = '\0';
  1423. #endif
  1424.  
  1425.     m = (struct mbx *)p;
  1426.  
  1427.     if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m)
  1428.        == -1){
  1429.     tputs((m->sid & MBX_SID) ? "NO - syntax error\n" : \
  1430.             "S command syntax error - format is:\n" \
  1431.             "S[C|F] name [@ host] [< from_addr] [$bulletin_id]\n" \
  1432.             "SR [number]\n");
  1433.     mail_error("%s: MBOX S syntax error - %s\n",m->name,m->line);
  1434.     return 0;
  1435.     }
  1436.  
  1437.     /*Check for send permission */
  1438.     if(m->privs & NO_SENDCMD) { /*is this to 'SYSOP' or 'sysop' ?*/
  1439.     if(stricmp(m->to,"sysop")) {
  1440.         tputs((m->sid & MBX_SID) ? "NO - permission denied\n" : \
  1441.             "Sorry, only mail to 'sysop' allowed!\n");
  1442.         mail_error("%s: no mail permission - %s\n",m->name,m->to);
  1443.         return 0;
  1444.     }
  1445.     }
  1446.     /* Check for a BID on bulletins from other bbs's - WG7J */
  1447.     if((m->sid & MBX_SID) && !NoBid &&
  1448.     (m->stype == 'B') && (m->tomsgid == NULLCHAR)) {
  1449.         tputs("NO - No BID!\n");
  1450.         log(m->user,"%s: SB without BID - %s",m->name,m->to);
  1451.         mail_error("%s: SB without BID - %s",m->name,m->to);
  1452.         return 0;
  1453.     }
  1454.  
  1455.     if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
  1456.         if(m->sid & MBX_SID)
  1457.             tputs("NO - ");
  1458.         tprintf("Already have %s\n",m->tomsgid);
  1459.         return 0;
  1460.     }
  1461.     if(m->stype == 'R' && !(m->sid & MBX_SID) &&
  1462.        mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
  1463.         return 0;
  1464.     if((cp = rewrite_address(m->to)) != NULLCHAR)
  1465.          if(strcmp(m->to,cp) != 0){
  1466.           m->origto = m->to;
  1467.           m->to = cp;
  1468.          }
  1469.          else
  1470.           free(cp);
  1471.  
  1472.     /* refuse any mail that gets rewritten into 'refuse' - WG7J */
  1473.     if(!strcmp(m->to,"refuse")) {
  1474.     tputs((m->sid & MBX_SID) ? "NO - refused\n" : \
  1475.         "Bad user or hostname,  please mail 'sysop' for help\n");
  1476.     return 0;
  1477.     }
  1478.  
  1479.     if( (!ThirdParty && !(m->privs & SYSOP_CMD)) || (m->privs & NO_3PARTY) )
  1480.         if(thirdparty(m) == 0){
  1481.         tputs(Mbwarning);
  1482.         mail_error("%s: 3rd party mail refused - %s\n",m->name,m->to);
  1483.             return 0;
  1484.         }
  1485.  
  1486.     /* Send the new 'To:' line to sysops only - WG7J */
  1487.     if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') \
  1488.      && !(m->sid & MBX_SID))
  1489.         tprintf("To: %s\n", m->to);
  1490.     if(validate_address(m->to) == 0){
  1491.     tputs((m->sid & MBX_SID) ? "NO - bad address\n" : \
  1492.         "Bad user or hostname,  please mail 'sysop' for help\n");
  1493.     free(rhdr);
  1494.         del_list(cclist);
  1495.         /* We don't free any more buffers here. They are freed upon
  1496.          * the next call to mbx_to() or to domboxbye()
  1497.          */
  1498.         return 0;
  1499.     }
  1500.     /* Display the Cc: line (during SR command) */
  1501.     for(ap = cclist; ap != NULLLIST; ap = ap->next) {
  1502.         if(cccnt == 0){
  1503.             tprintf("%s",Hdrs[CC]);
  1504.             cccnt = 4;
  1505.         }
  1506.         else {
  1507.             tputs(", ");
  1508.             cccnt += 2;
  1509.         }
  1510.         if(cccnt + strlen(ap->val) > 80 - 3) {
  1511.             tputs("\n    ");
  1512.             cccnt = 4;
  1513.         }
  1514.         tputs(ap->val);
  1515.         cccnt += strlen(ap->val);
  1516.     }
  1517.     if(cccnt)
  1518.         tputc('\n');
  1519.  
  1520.     /* If the the command was 'SC' then read the Cc: list now - WG7J */
  1521.     if((m->stype == 'C') && !(m->sid & MBX_SID)) {
  1522.     m->stype = 'P'; /* make everything private */
  1523.     tputs(CcLine);
  1524.     if(mbxrecvline(m) != -1) {
  1525.         if(strlen(m->line)) {
  1526.         if(*m->line == 0x01) { /* CTRL-A, abort */
  1527.             free(rhdr);
  1528.             del_list(cclist);
  1529.             tputs(MsgAborted);
  1530.             return 0;
  1531.         }
  1532.         cp = m->line;
  1533.         /* get all the Cc addresses, separated by comma's */
  1534.         while((cp2=strchr(cp,',')) != NULLCHAR) {
  1535.             *cp2 = '\0';
  1536.             /*get rid of leading spaces or tabs*/
  1537.             while(*cp == ' ' || *cp == '\t')
  1538.             cp++;
  1539.             if(strlen(cp))
  1540.             addlist(&cclist,cp,0);
  1541.             cp = cp2 + 1;
  1542.         }
  1543.         /* Do the last or only one */
  1544.         /* get rid of leading spaces or tabs*/
  1545.         while(*cp == ' ' || *cp == '\t')
  1546.             cp++;
  1547.         if(strlen(cp))
  1548.             addlist(&cclist,cp,0);
  1549.         }
  1550.     } else {
  1551.         free(rhdr);
  1552.         del_list(cclist);
  1553.         return 0;
  1554.     }
  1555.     }
  1556.  
  1557.     /* Now check to make sure we can create the needed tempfiles - WG7J */
  1558.     if((m->tfile = tmpfile()) == NULLFILE) {
  1559.     free(rhdr);
  1560.     del_list(cclist);
  1561. /*
  1562.     tputs((m->sid & MBX_SID) ? "NO - no temp file\n" : \
  1563.         "Can't create temp file for mail\n");
  1564.     return 0;
  1565.  */
  1566.     /* instead of saying NO and have the other bbs think we already
  1567.      * have the message, disconnect !
  1568.      */
  1569.     if(m->sid & MBX_SID)
  1570.         return -2;
  1571.     /* tell regualr users about it */
  1572.     tputs("Can't create temp file for mail\n");
  1573.     return 0;
  1574.      }
  1575. #ifdef RLINE
  1576.     /* Only accept R: lines from bbs's */
  1577.     if((m->sid & MBX_SID)&&(Rdate || Rreturn || Rfwdcheck || Mbloophold)){
  1578.     /* Going to interpret R:headers,
  1579.      * we need another tempfile !
  1580.      */
  1581.     if((m->tfp = tmpfile()) == NULLFILE) {
  1582.         free(rhdr);
  1583.         del_list(cclist);
  1584. /*
  1585.         tputs("NO - no temp file\n");
  1586.         return 0;
  1587.  */
  1588.         /* disconnect to avoid the other bbs to think that we already have
  1589.          * the message !
  1590.          */
  1591.         return -2;
  1592.      }
  1593.     /* Now we got enough :-) */
  1594.     check_r = 1;
  1595.     Checklock++;
  1596.     /* Set the call, used in loop detect code - WG7J */
  1597.     if(Mbloophold) {
  1598.         pax25(Me,Mycall);
  1599.         if((cp = strchr(Me,'-')) != NULLCHAR)
  1600.         *cp = '\0'; /* remove SSID */
  1601.     }
  1602.     }
  1603. #endif
  1604.  
  1605.     m->state = MBX_SUBJ;
  1606.     if(m->stype != 'R' || (m->sid & MBX_SID)) {
  1607. /* This might bollix incoming forwarding, we'll see:  suggested by
  1608.    N6NKO in mail that \n after Subject: become a space.  Brandon */
  1609.     tputs((m->sid & MBX_SID) ? "OK\n" : "Subject: ");
  1610.     if(mbxrecvline(m) == -1) {
  1611. #ifdef RLINE
  1612.         if(check_r) {
  1613.         MYFCLOSE(m->tfp);
  1614.         Checklock--;
  1615.         }
  1616. #endif
  1617.         return 0;
  1618.     }
  1619.     }
  1620.     else                            /* Replying to a message */
  1621.         tprintf("Subject: %s\n",m->line);
  1622.  
  1623.     m->subject = strdup(m->line);
  1624.  
  1625. #ifdef RLINE
  1626.     if(!check_r) {
  1627. #endif
  1628.     mbx_data(m,cclist,rhdr);
  1629.     /*Finish smtp headers*/
  1630.     fprintf(m->tfile,"\n");
  1631. #ifdef RLINE
  1632.     }
  1633. #endif
  1634.     free(rhdr);
  1635.     m->state = MBX_DATA;
  1636.     if(!(m->sid & MBX_SID) && m->stype != 'F')
  1637.         tprintf("Enter message.  %s",Howtoend);
  1638.  
  1639.     if(m->stype != 'F' || (m->sid & MBX_SID) != 0) {
  1640.     while(mbxrecvline(m) != -1){
  1641.             if(m->line[0] == 0x01){  /* CTRL-A */
  1642.         MYFCLOSE(m->tfile);
  1643. #ifdef RLINE
  1644.         if(check_r)
  1645.             MYFCLOSE(m->tfp);
  1646. #endif
  1647.         tputs(MsgAborted);
  1648.                 del_list(cclist);
  1649.                 return 0;
  1650.             }
  1651.         if(m->line[0] != CTLZ && stricmp(m->line, "/ex")) {
  1652. #ifdef RLINE
  1653.         if(check_r) {
  1654.             /* Check for R: lines to start with */
  1655.             if(!strncmp(m->line,"R:",2)) { /*found one*/
  1656.             found_r = 1;
  1657.             /*Write this line to the second tempfile
  1658.              *for later rewriting to the real one
  1659.              */
  1660.             fprintf(m->tfp,"%s\n",m->line);
  1661.             /* Find the '@[:]CALL.STATE.COUNTRY'or
  1662.              * or the '?[:]CALL.STATE.COUNTRY' string
  1663.              * The : is optional.
  1664.              */
  1665.             if( ((cp=strchr(m->line,'@')) != NULLCHAR) ||
  1666.                 ((cp=strchr(m->line,'?')) != NULLCHAR) ) {
  1667.                 if((cp2=strchr(cp,' ')) != NULLCHAR)
  1668.                 *cp2 = '\0';
  1669.                 if((cp2=strchr(cp,'\n')) != NULLCHAR)
  1670.                 *cp2 = '\0';
  1671.                 if((cp2=strchr(cp,'\t')) != NULLCHAR)
  1672.                 *cp2 = '\0';
  1673.                 /* Some bbs's send @bbs instead of @:bbs*/
  1674.                 if (*++cp == ':')
  1675.                 cp++;
  1676.                 /* if we use 'return addres'
  1677.                  * copy whole 'domain' name
  1678.                  */
  1679.                 if(Rreturn)
  1680.                 if(strlen(cp) <= OBLEN)
  1681.                     strcpy(origbbs,cp);
  1682.                 /* Optimize forwarding ? */
  1683.                 if(Rfwdcheck || Mbloophold) {
  1684.                 /*if there is a HADDRESS, cut off after '.'*/
  1685.                 if((cp2=strchr(cp,'.')) != NULLCHAR)
  1686.                     *cp2 = '\0';
  1687.                 if(Mbloophold)
  1688.                     /* check to see if this is my call ! */
  1689.                     if(!stricmp(Me,cp))
  1690.                     loops++;
  1691.                 /*cross-check with MyFwds list*/
  1692.                 if(Rfwdcheck) {
  1693.                     for(i=0;i<Numfwds;i++) {
  1694.                     if(!strcmp(MyFwds[i],cp)) {
  1695.                         /*Found one !*/
  1696.                         strcpy(fwdbbs[myfwds++],cp);
  1697.                         break;
  1698.                     }
  1699.                     }
  1700.                 }
  1701.                 }
  1702.             }
  1703.             if(Rdate) {
  1704.                 /* Find the 'R:yymmdd/hhmmz' string */
  1705.                 if((cp=strchr(m->line,' ')) != NULLCHAR) {
  1706.                 *cp = '\0';
  1707.                 if(strlen(m->line+2) <= ODLEN)
  1708.                     strcpy(origdate,m->line+2);
  1709.                 }
  1710.             }
  1711.             } else {
  1712.             /* The previous line was last R: line
  1713.              * so we're done checking
  1714.              * now write the smtp headers and
  1715.              * all saved R: lines to the right tempfile
  1716.              */
  1717.             check_r = 0;
  1718.             Checklock--;
  1719.             /*Did we actually find one ?*/
  1720.             if(found_r) {
  1721.                 if(Rreturn)
  1722.                 m->origbbs = strdup(strlwr(origbbs));
  1723.                 if(Rdate) {
  1724.                 if((cp=strchr(origdate,'/')) != NULLCHAR) {
  1725.                     zulu = 0; /* not initialized before! */
  1726.                     if((*(cp+5) == 'z') || (*(cp+5) == 'Z')) {
  1727.                     *(cp+5) = '\0';
  1728.                     zulu = 1;
  1729.                     }
  1730.                     t.tm_min = atoi(cp+3);
  1731.                     *(cp+3) = '\0';
  1732.                     t.tm_hour = atoi(cp+1);
  1733.                     *cp = '\0';
  1734.                     t.tm_mday = atoi(&origdate[4]);
  1735.                     origdate[4] = '\0';
  1736.                     t.tm_mon = (atoi(&origdate[2]) - 1);
  1737.                     origdate[2] = '\0';
  1738.                     t.tm_year = atoi(origdate);
  1739.                     /* Set the date in rfc 822 format */
  1740.                     m->date = mallocw(40);
  1741.                     sprintf(m->date,"%.2d %s %02d %02d:%02d:00 %.3s\n",
  1742.                     t.tm_mday,
  1743.                     Months[t.tm_mon],
  1744.                     t.tm_year,
  1745.                     t.tm_hour,
  1746.                     t.tm_min,
  1747.                     zulu ? "UTC" : "");
  1748.                 }
  1749.                 }
  1750.             }
  1751.             /* Now write the headers,
  1752.              * possibly adding Xforwarded lines for bulletins,
  1753.              * or anything that has a BID.
  1754.              * Add the X-Forwarded lines and loop detect
  1755.              * headers FIRST,
  1756.              * this speeds up forwarding...
  1757.              */
  1758.             if(Mbloophold && loops >= Mbloophold)
  1759.                 fprintf(m->tfile,"%sLoop\n",Hdrs[XBBSHOLD]);
  1760.             if(Rfwdcheck && found_r && \
  1761.                ((m->stype == 'B') || (m->tomsgid)) ){
  1762.                 /*write Xforwarded headers*/
  1763.                 for(i=0;i<myfwds;i++) {
  1764.                 fprintf(m->tfile,"%s%s\n",Hdrs[XFORWARD],fwdbbs[i]);
  1765.                 }
  1766.             }
  1767.             /*write regular headers*/
  1768.             mbx_data(m,cclist,rhdr);
  1769.             /* Finish smtp headers */
  1770.             fprintf(m->tfile,"\n");
  1771.  
  1772.             /* Now copy the R: lines back */
  1773.             if(found_r) {
  1774.                 rewind(m->tfp);
  1775.                 while(fgets(tmpline,sizeof(tmpline),m->tfp)!=NULLCHAR)
  1776.                 fputs(tmpline,m->tfile);
  1777.             }
  1778.             MYFCLOSE(m->tfp);
  1779.  
  1780.             /* And add this first non-R: line */
  1781.             fprintf(m->tfile,"%s\n",m->line);
  1782.             }
  1783.         } else
  1784. #endif
  1785.                 fprintf(m->tfile,"%s\n",m->line);
  1786.         } else {
  1787. #ifdef RLINE
  1788.         if(check_r) {
  1789.             /* Hmm, this means we never finished the R: headers
  1790.              * tmp file still open !
  1791.              */
  1792.             MYFCLOSE(m->tfp);
  1793.         }
  1794. #endif
  1795.         done = 1; /* To indicate the difference between
  1796.                * mbxrecvline() returning -1 and /ex ! - WG7J
  1797.                * Now also used to indicate if the message should
  1798.                * be sent or not !
  1799.                */
  1800.         /* Now ask users if they want to send this ! - WG7J */
  1801.         if( Mbsendquery && !(m->sid & MBX_SID)) {
  1802.             if(m->type == TELNET_LINK || m->type == TIP_LINK)
  1803.             c = tkeywait("Send(N=no)?",0,m->linemode);
  1804.             else  /* For AX.25 and NET/ROM connects */
  1805.             c = mykeywait("Send(N=no)?",m);
  1806.             if(c == -1 || c == 'n' || c == 'N') {
  1807.             done = 0;   /* signal delete of message */
  1808.             tputs(MsgAborted);
  1809.             }
  1810.         }
  1811.         break;  /* all done */
  1812.         }
  1813.         }
  1814.     if(!done) {
  1815.         /* We did NOT get ^Z or /EX, but mbxrecvline returned -1 !!!
  1816.          * This means the connection is gone ! - WG7J
  1817.          * Now can also mean that the user doesn't want to send msg !
  1818.          */
  1819.         MYFCLOSE(m->tfile);
  1820. #ifdef RLINE
  1821.         if(check_r)
  1822.         MYFCLOSE(m->tfp);
  1823. #endif
  1824.         del_list(cclist);
  1825.         free(rhdr); /*Just in case*/
  1826.         return 0;
  1827.     }
  1828.     } else {
  1829.         fprintf(m->tfile,"----- Forwarded message -----\n\n");
  1830.         msgtofile(m,m->current,m->tfile,0);
  1831.         fprintf(m->tfile,"----- End of forwarded message -----\n");
  1832.     }
  1833.  
  1834.     /* Insert customised signature if one is found */
  1835.     if(!(m->sid & MBX_SID)) {       /* not a forwarding BBS */
  1836.          sprintf(sigwork,"%s/%s.sig",Signature,
  1837.              m->tofrom ? m->tofrom : m->name);
  1838.          if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE){
  1839.           while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
  1840.             fputs(sigwork,m->tfile);
  1841.           fclose(fp);
  1842.          }
  1843.     }
  1844.  
  1845.     if((host = strrchr(m->to,'@')) == NULLCHAR) {
  1846.         host = Hostname;        /* use our hostname */
  1847.         if(m->origto != NULLCHAR) {
  1848.             /* rewrite_address() will be called again by our
  1849.              * SMTP server, so revert to the original address.
  1850.              */
  1851.             free(m->to);
  1852.             m->to = m->origto;
  1853.             m->origto = NULLCHAR;
  1854.         }
  1855.     }
  1856.     else
  1857.         host++; /* use the host part of address */
  1858.  
  1859.     /* make up full from name for work file */
  1860.     if(m->tofrom != NULLCHAR)
  1861.         sprintf(fullfrom,"%s%%%s@%s",m->tofrom, m->name, Hostname);
  1862.     else
  1863.         sprintf(fullfrom,"%s@%s",m->name,Hostname);
  1864.     if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
  1865.         fseek(m->tfile,0L,0);   /* reset to beginning */
  1866.         fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
  1867.         del_list(cclist);
  1868.         cclist = NULLLIST;
  1869.     }
  1870.     addlist(&cclist,m->to,0);
  1871.     fseek(m->tfile,0L,0);
  1872.     fail += queuejob(m->tfile,host,cclist,fullfrom);
  1873.     del_list(cclist);
  1874.     MYFCLOSE(m->tfile);
  1875.     if(fail){
  1876.     if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
  1877.         tputs("Couldn't queue msg!\n");
  1878.     } else {
  1879.     if(m->sid & MBX_SID)
  1880.         MbRecvd++;
  1881.     else {
  1882.         tputs("Msg queued\n");
  1883.         MbSent++;
  1884.     }
  1885. #ifdef notdef
  1886.     /* BID is now saved in the smtp server ! - WG7J */
  1887.     if(m->tomsgid != NULLCHAR && \
  1888.       (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
  1889.         /* Timestamp added to allow automatic expiry of bid file - WG7J */
  1890.         time(&now);
  1891.         fprintf(fp,"%s %ld\n",m->tomsgid,now); /* Save BID */
  1892.         fclose(fp);
  1893.     }
  1894. #endif
  1895.     }
  1896.     smtptick(NULL);     /* wake SMTP to send that mail */
  1897.     return 0;
  1898. }
  1899. #endif /* MAILCMDS */
  1900.  
  1901. #endif /* MAILBOX */
  1902.